import * as step from '@flow-step/step-toolkit'
import {SaeInterface} from './sae'
import {DeployApplicationRequest, DescribeApplicationConfigRequest, DescribeApplicationConfigResponse} from '@alicloud/sae20190506'
import {getDateVersion, printJSON} from './utils'
import {IParams} from './params'

export async function describeConfig(params: IParams, sae: SaeInterface) {

    step.info(`checking status for current application`)
    step.info(`GETTING APPLICATION CONFIG`)
    const request = new DescribeApplicationConfigRequest({
        appId: params.APPLICATION_ID
    })

    let response: DescribeApplicationConfigResponse
    try {
        response = await sae.describeApplicationConfig(request)
    } catch (error) {
        throw new Error(`failed to describeApplicationConfig: ${error}`)
    }
    if (!response.body || !response.body.data || response.body.code != '200'){
        throw new Error(`failed to get application config, please check the SAE console`)
    }
    step.info(`[USER] Application Config`)
    printJSON(response.body.data)

    if (!response.body.data.appName || !response.body.data.packageType){
        throw new Error(`appName or packageType is not found, please check the application config`)
    }
    const appName = response.body.data.appName
    const packageType = response.body.data.packageType
    step.info(`[USER]APPLICATION_ID=${params.APPLICATION_ID}`)
    step.info(`[USER]ARTIFACT=${params.ARTIFACT}`)
    step.info(`[USER]PACKAGE=${params.PACKAGE}`)
    step.info(`[USER]APP_NAME=${appName}`)
    step.info(`[USER]Package_Type=${packageType}`)
    step.info(`[USER]StrategyType=${params.StrategyType}`)
    step.info(`[USER]GrayNumber=${params.GrayNumber}`)
    step.info(`[USER]minReadyInstances=${params.minReadyInstances}`)
    step.info(`[USER]minReadyInstanceRatio=${params.minReadyInstanceRatio}`)
    step.info(`[USER]Batch=${params.Batch}`)
    step.info(`[USER]BatchWaitTime=${params.BatchWaitTime}`)
    step.info(`[USER]ReleaseType=${params.ReleaseType}`)
    return response.body.data
}

export function generateDeployRequest(params: IParams, packageType: string) {
    const packageJson = JSON.parse(params.PACKAGE)
    const artifactUrl = packageJson.ARTIFACT_URL
    const dockerUrl = packageJson.DOCKER_URL
    const artifactName = packageJson.ARTIFACT_NAME
    const packageVersion = getDateVersion()

    step.info('THE DEPLOYMENT TASK BEGINS')

    if (artifactUrl){
        step.info(`[USER]ARTIFACT_URL=${artifactUrl}`)
        step.info(`[USER]ARTIFACT_NAME=${artifactName}`)
        step.info(`Start upgrading application version to: ${artifactUrl}`)
    }else if (dockerUrl){
        step.info(`[USER]IMAGE_URL=${dockerUrl}`)
        step.info(`Start upgrading application version to: ${dockerUrl}`)
    }

    step.info(`[USER]PACKAGE_VERSION=${packageVersion}`)

    const updateStrategy = getUpdateStrategy(params)

    const deployRequest = new DeployApplicationRequest({
        appId: params.APPLICATION_ID,
        packageVersion: packageVersion,
        updateStrategy: updateStrategy,
        batchWaitTime: Number(params.waitTimeInBatch || '10')
    })

    if (params.enableGreyTagRoute) {
        deployRequest.enableGreyTagRoute = Boolean(params.enableGreyTagRoute)
    }

    if (packageType.toLowerCase().includes('image')) {
        deployRequest.imageUrl = dockerUrl
    } else {
        deployRequest.packageUrl = artifactUrl
    }

    if (params.USE_ACR_EE) {
        deployRequest.acrInstanceId = params.ACR_EE_ID
    }

    if (params.minReadyInstanceType == 'byNumber') {
        deployRequest.minReadyInstances = Number(params.minReadyInstances)
    } else if (params.minReadyInstanceType == 'byRatio') {
        deployRequest.minReadyInstanceRatio = Number(params.minReadyInstanceRatio)
    } else {
        throw new Error('minReadyInstanceType is not valid')
    }
    step.debug(`[USER]deployRequest=${JSON.stringify(deployRequest)}`)
    return deployRequest
}

export function getUpdateStrategy(params: IParams) {
    let updateStrategy: string
    switch (params.StrategyType) {
        case 'BatchUpdate':
            updateStrategy = JSON.stringify({
                type: params.StrategyType,
                batchUpdate: {
                    batch: params.Batch,
                    releaseType: params.ReleaseType,
                    batchWaitTime: params.BatchWaitTime
                }
            })
            break
        case 'GrayBatchUpdate':
            updateStrategy = JSON.stringify({
                type: params.StrategyType,
                batchUpdate: {
                    batch: params.Batch,
                    releaseType: params.ReleaseType,
                    batchWaitTime: params.BatchWaitTime
                },
                grayUpdate: {
                    gray: params.GrayNumber
                }
            })
            break
        default:
            throw new Error('missing deployStrategy')
    }
    return updateStrategy
}